/**
 * <p>文件名:		BaseThriftServerFactory.java</p>
 * <p>版权:		CopyrightTag</p>
 * <p>公司:		CompanyTag</p>
 * @author		周华彬(zhouhuabin@ctfo.com, zhou_hua_bin@163.com)
 */

package com.caits.lbs.framework.services.thrift;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;
import org.apache.thrift.TProcessor;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.springframework.beans.factory.InitializingBean;

import com.caits.lbs.exception.LBSRuntimeException;
import com.caits.lbs.framework.log.CommonLogFactory;

/**
 * <p>
 * BaseThriftServerFactory
 * </p>
 * <p>
 * TODO
 * </p>
 *
 * @author 周华彬(zhouhuabin@ctfo.com, zhou_hua_bin@163.com)
 * @version 0.0.0
 *          <table style="border:1px solid gray;">
 *          <tr>
 *          <th width="100px">版本号</th>
 *          <th width="100px">动作</th>
 *          <th width="100px">修改人</th>
 *          <th width="100px">修改时间</th>
 *          </tr>
 *          <!-- 以 Table 方式书写修改历史 -->
 *          <tr>
 *          <td>0.0.0</td>
 *          <td>创建类</td>
 *          <td>zhouhuabin</td>
 *          <td>2014年11月19日 下午5:23:47</td>
 *          </tr>
 *          <tr>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          <td>XXX</td>
 *          </tr>
 *          </table>
 */
public class BaseThriftServerFactory implements InitializingBean {

	/** 服务模式：阻塞的普通模式 */
	public static final int THRIFTSERVER_MODEL_BIO = 1;
	/** 服务模式：非阻塞的压缩模式 */
	public static final int THRIFTSERVER_MODEL_NIO = 2;
	/** 日志记录器 */
	protected Logger log = CommonLogFactory.getLog();
	/** 要服务的接口列表 */
	private TProcessor processor;

	/** 服务实例 */
	private TServer server;
	/** thrift服务的tcp侦听端口 */
	private int listenPort;
	/** 服务模式 */
	private int serverModel = THRIFTSERVER_MODEL_NIO;

	/**
	 * 普通服务模式初始化
	 *  服务端类型 * 
	 *  TSimpleServer - 单线程服务器端使用标准的堵塞式 I/O。 
	 *  TThreadPoolServer - 多线程服务器端使用标准的堵塞式 I/O。 
	 *  TNonblockingServer – 多线程服务器端使用非堵塞式 I/O，并且实现了 Java 中的 NIO 通道
	 */
	private void initBlockingModelServer() {
		try {
			TServerTransport serverTransport = new TServerSocket(new InetSocketAddress("0.0.0.0", listenPort));
			Args trArgs = new Args(serverTransport);
			/**TTransport协议类型参见thrift.txt文件 */
			trArgs.protocolFactory(new TCompactProtocol.Factory());
			trArgs.transportFactory(new TFramedTransport.Factory());
			trArgs.processorFactory(new TProcessorFactory(processor));
			server = new TThreadPoolServer(trArgs);
			Runnable command = new Runnable() {
				@Override
				public void run() {
					log.info("thrift server started on port " + listenPort);
					server.serve();
				}
			};
			Executors.newSingleThreadExecutor().execute(command);
		} catch (Exception e) {
			log.error("thrift服务启异常:阻塞&二进制编码,msg=" + e.getLocalizedMessage(), e);
			throw new LBSRuntimeException("base thrift server start failed,msg=" + e.getMessage());
		}
	}

	/**
	 * 高效率的、密集的二进制编码格式进行数据传输服务模式
	 */
	private void initNonBlockingModelServer() {
		try {
			TNonblockingServerSocket socket = new TNonblockingServerSocket(listenPort);
			THsHaServer.Args arg = new THsHaServer.Args(socket);
			/**TProtocol协议类型参见thrift.txt文件 */
			arg.protocolFactory(new TCompactProtocol.Factory());
			arg.transportFactory(new TFramedTransport.Factory());
			arg.processorFactory(new TProcessorFactory(processor));
			log.info("thrift服务启动-使用:非阻塞&高效二进制编码");
			//单线程 non blocking的服务
//			server = new TNonblockingServer(arg);
			// 多线程 non blocking的服务
			server = new THsHaServer(arg);
			Runnable command = new Runnable() {
				@Override
				public void run() {
					log.info("thrift 服务启动-使用:非阻塞&压缩二进制编码, on port=" + listenPort);
					server.serve();
				}
			};
			Executors.newSingleThreadExecutor().execute(command);
		} catch (Exception e) {
			log.error("thrift服务启异常:非阻塞&压缩二进制编码,msg=" + e.getLocalizedMessage(), e);
			throw new LBSRuntimeException("base thrift server start failed,msg=" + e.getMessage());
		}
	}

	/**
	 * 字段 processor 获取函数
	 * 
	 * @return the processor : TProcessor
	 */
	public TProcessor getProcessor() {
		return processor;
	}

	/**
	 * 字段 processor 设置函数 : TProcessor
	 * 
	 * @param processor
	 *            the processor to set
	 */
	public void setProcessor(TProcessor processor) {
		this.processor = processor;
	}

	/**
	 * 字段 listenPort 获取函数
	 * 
	 * @return the listenPort : int
	 */
	public int getListenPort() {
		return listenPort;
	}

	/**
	 * 字段 listenPort 设置函数 : int
	 * 
	 * @param listenPort
	 *            the listenPort to set
	 */
	public void setListenPort(int listenPort) {
		this.listenPort = listenPort;
	}

	/**
	 * 字段 serverModel 获取函数
	 * @return the serverModel : int
	 */
	public int getServerModel() {
		return serverModel;
	}

	/**
	 * 字段 serverModel 设置函数 : int
	 * @param serverModel the serverModel to set
	 */
	public void setServerModel(int serverModel) {
		this.serverModel = serverModel;
	}

	/**
	 * 停止服务器
	 */
	public void destroy() {
		if (server != null)
			server.stop();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		if (serverModel == THRIFTSERVER_MODEL_NIO){
			initNonBlockingModelServer();
		}
		else{
			initBlockingModelServer();
		}
	}
}
